import tkFileDialog as tk
import numpy as np
import pylab as lab
import pyfits 
from glob import glob
import os, csv, math, shutil, sys
from reduice import*
import divide
import tkMessageBox

def SubtractBias(path=None, outdir=None):
    '''(str,str) -> None 
    Opens the various directories(Dark,Flat and Light) and prepares  
    subtracts the master bais form all the fits files and stores them in Biased dir'''
	#get files if no path is passed then gui will come up
    if path == None:
        path = gui_getdir(title='Please Select FITS Directory')
        #get biases and fits header list
        bias_dic,bias_hdr = get_bias(path+'/Bias',outdir=path+'/Reduced')
        if bias_dic == {}:
            raise
        #decoupling the tuple and dictionary to get the indiviual bias and hdr arrays 
    	bias = bias_dic.values()[0]
    	hdr = bias_hdr.values()[0]
    	dim_bias = get_dim(hdr)
    	         
        #gets all the files in a dir and all its sub dirs
    	files = divide.get_filelist(path)
    path += 'Reduced/Biased'
 
	#Loops through all the files in the dir
    for fit in files:
		if not fitype(fit,'Bias'): #rejects all bias files and the non-fits files
			#print 'not afits'+fit
			continue
		#gets the array and header of the fit 
		fits_array, hdr_fit = fromfits( fit,verbose=False )

		dim_fits = get_dim(hdr_fit)

		#checks if the bias and fits have the same dimension
		if dim_fits == dim_bias:
			new_array = fits_array - bias
		else:
			print 'arrays not the same sizes'
			continue
			
		savefits('bias subtracted',path,fit, new_array,hdr_fit)
			
def RemoveDarks(path=None):
    ''' Removes master dark from fits from the flatfielded dir and stores them in Darked dir'''

    if path is None:
		path = gui_getdir(title='Please Select FITS Directory')
	#gets darks
    dark_dic,hdr = get_darks(path=path+'/Darks', outdir=path+'/Reduced')

	#gets all the fits which biased hased been removed
    light_dir = glob(path+'/Reduced/Biased/*')
    path += 'Reduced/Darked'

	#decompling the dark arrays and header
    darks = dark_dic.values()
    hdrs = hdr.values()

	#iterates throught the darks
    for i in xrange(len(darks)):
        #exposure time of the ith dark
        dark_exptime = hdrs[i]['EXPTIME']
        #array of the ith dark
        dark_array = darks[i]
        #dimension of the ith dark 
        dim_dark = get_dim(hdrs[i]) 
  		
  		#iterates through the biased fits
        for fit in light_dir:
            #checks if fit is a fits, also rejects darks
            if not fitype(fit,'Dark'): 
				print 'not a fits'+fit
				continue
            #exposure time of the fit
            light_exptime = pyfits.getval(fit,'EXPTIME') 
            # the ratio of expected time of light and dark
            factor = light_exptime / dark_exptime 
            fits_array,	hdr = fromfits( fit ,verbose=False)
            #dimension of fits
            dim_fits = get_dim(hdr) 
			#checks dimensions
            if dim_fits == dim_dark:
                new_array = fits_array - dark_array * factor
            else: 
                print 'arrays not the same sizes'
            savefits('dark removed', path , fit, new_array,hdr)

def RemoveFlat(path=None):
	'''Divides the master flat from the fits and stores them in Flatfielded'''

	if path is None:
		path = gui_getdir(title='Please Select fits Directory')
 
	flats_dic,hdr =get_flats(path=path+'/Flats', outdir=path+'/Reduced/')
	lights = glob(path+'/Reduced/Darked/*')

	if len(lights) == 0: 
	#no darks
		print 'There are no darks. Calibration may not be accurate.'
		#use bias
		lights = glob(path+'/Reduced/Biased/*') 

	#removes flat only on lights
	lights = get_fits_type(lights,'light') 
	flats = flats_dic.values()  
	flit = flats_dic.keys()  
	hdrs = hdr.values()
	path += 'Reduced/Flatfielded'

	#iterating through the different filter flats
	for i in xrange(len(flats)):
		Filter = flit[i]
		dim_flat = get_dim(hdrs[i])
  
		#iterating through the light files(biased or darked)
		for light in lights:
			
			light_filt = str(pyfits.getval(light,'FILTER'))
			#checks if the filters are the same   
			if Filter == light_filt:
				flat_arry = flats[i]
   
				light_arry ,hdr = fromfits(light,verbose=False)
    
				dim_fits = get_dim(hdr)
                #divide out flats (wrong)
				if dim_fits == dim_flat:
					light_arry /= (flat_arry)
					light_arry *= flat_arry.max() 
				else:
					print 'arrays not the same sizes'

				savefits('flat divided',path,light,light_arry,hdr)
				
  
def savefits(hsty,path,fit,arry,hdr):
    '''(str,str,str,str)->None
	The method saves fits into their new dirs'''
    assert os.path.exists(path),'No such file or directory'
    new_path=fit[fit.rfind('/'):]
    hdr.add_history(hsty)
    tofits(path + new_path ,arry , hdr)
	
def get_dim(hdr):
	'''Returns the dimensions of fit
	str -> tuple'''
	return (hdr['NAXIS1'],hdr['NAXIS2'])


def fitype(fit,ftype=None):
	'''Returns True if the fit is of type ftype (Dark or Bias)
	param fit: is the fit file of intrest
	param ftye: is the type of fit(bais,flat). If ftype is None then
	 the method just checks if fit is a fits file, returns True is its a fits'''
 
	if not (fit.endswith('.fit') or fit.endswith('.fits')):
		return False
	if ftype != None:
		if pyfits.getval(fit,'IMAGETYP') == ftype+' Frame':
			return False

	return True
 

 
 
